/**
 * 类修饰器  拓展类的属性和方法
 */

// const decorator = (target:any) => {
//     target.prototype.name = 'decorator'
//     target.prototype.age = 18
// }

// @decorator
// class AA{
//     constructor(){

//     }
// }

// const aa = new AA() as any
// console.log(aa.name,aa.age)


/**
 * 方法修饰器 类似语在装饰器中理由回调函数触发类的方法  比如请求等等 
 */

// const methodDecorator:MethodDecorator = (target:any,propertyKey:string | symbol,descriptor:PropertyDescriptor)=>{
//     //实现记录方法的参数信息和方法的名字
//     var originmethod = descriptor.value 
//     descriptor.value = function(...args:any[]){
//         console.log(args)
//         console.log(propertyKey)
//         return originmethod.apply(this,args)
//     }
// }

// class BB {
//     constructor(){}
//     @methodDecorator
//     add(a:number,b:number){
//         return a+b
//     }
// }

// const bb = new BB()
// console.log(bb.add(1,2))



/**
 * 
 * 属性装饰器 可以通过Object.defineProperty()来修改属性的特性 对属性的输入值进行限制
 */

// const propertyDecorator:PropertyDecorator = (target:any,propertyKey:string | symbol)=>{
//     let value = target[propertyKey]
//     Object.defineProperty(target,propertyKey,{
//         get() {
//             return value
//         },
//         set(v) {
//             if(v < 0){
//                 throw new Error('值不能小于0')
//             }
//             value = v
//         },
//     })
// }

// class CC {
//     @propertyDecorator
//     age:number;
//     constructor(age:number){
//         this.age = age;
//     }
// }

// const cc = new CC(-1)


/**
 * 
 * 参数装饰器 实现传入参数显示对应的属性值
 */
import 'reflect-metadata';

const propertyMethod = (propertyKey:string)=>{
    return (target:Object,methodKey:string|symbol,propertyIndex:number)=>{
        Reflect.defineMetadata(`extract_property:${propertyKey}:${propertyIndex}`,methodKey,target,methodKey)
    }
}

const adjustProperty = (target:Object,methodKey:string,args:any[])=>{
    const reflectKeys = Reflect.getOwnMetadataKeys(target,methodKey).filter((key:string)=>{
        return key.startsWith('extract_property')
    }).map((key:string)=>{
        const propertyKey = key.split(':')[1]
        const propertyIndex = Number(key.split(':')[2])
        return {
            propertyKey,
            propertyIndex
        }
    })
    reflectKeys.forEach((item)=>{
        const {propertyIndex,propertyKey} = item
        const arg = args[propertyIndex]
        if(arg && propertyKey in arg){
            args[propertyIndex] = arg[propertyKey]
        }
    })
}

class DD{
    getinfo(@propertyMethod('name')info:any){
        console.log(info)
    }
}
const dd = new DD()

const params = {name:'zss',age:12}
const args = [params]

adjustProperty(DD.prototype,'getinfo',args)

dd.getinfo(args)

